﻿using System;
using System.Data;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;
using Estimate.Common.Repository;
using Estimate.Common.Entity;
using Estimate.Common.DBFieldTypes;
using Estimate.Common.Estimate;

namespace Estimate.Common.DBHealth
{
   
    /// <summary>
    /// 检测实况数据的问题
    /// </summary>
    public class RealHealth
    {
        public bool CheckLackRecord = true;
        public bool CheckEmptyValue = true;
        public bool CheckRepeatStation = true;
        public bool CheckLackStation = true;
        public bool CheckAbnormalStation = true;
        public bool CheckValue = true;

        RainRealRepository RepositoryRailReal;
        TempRealRepository RepositoryTempReal;
        DateTime BeginDate;
        DateTime EndDate;
        RealDataType DataType;
        string ConnectionString;

        private Dictionary<string, int> _autoStations;
        private Dictionary<string, int> _manualStations;

        public RealHealth()
        {
            ConnectionString = ConfigurationManager.AppSettings["ConnectionString"];

            _autoStations = new Dictionary<string, int>();
            _manualStations = new Dictionary<string, int>();
        }

       /// <summary>
       /// 检查降水、温度实况数据
       /// </summary>
       /// <param name="beginDate"></param>
       /// <param name="endDate"></param>
       /// <param name="dataType">实况数据类型</param>
       /// <returns></returns>
        public DataTable CheckHealth(DateTime beginDate, DateTime endDate,RealDataType dataType)
        {
            BeginDate = beginDate;
            EndDate = endDate;
            DataType = dataType;

            DataTable CheckResult = new DataTable();
            CheckResult.Columns.Add("说明");
            CheckResult.Columns.Add("表名");
            CheckResult.Columns.Add("日期");
            CheckResult.Columns.Add("类型");

            CheckResult.DefaultView.Sort = "表名 asc,说明 asc,日期 asc";
            if (dataType == RealDataType.auto_rain)
                RepositoryRailReal = RainRealRepositoryFactory.AutoStationRainRealRepository(ConnectionString);
            else if (dataType == RealDataType.manual_rain)
                RepositoryRailReal = RainRealRepositoryFactory.ManualRainRealRepository(ConnectionString);
            else if (dataType == RealDataType.auto_temp)
                RepositoryTempReal = TempRealRepositoryFactory.AutoStationTempRealRepository(ConnectionString);
            else if (dataType == RealDataType.manual_temp)
                RepositoryTempReal = TempRealRepositoryFactory.ManualTempRealRepository(ConnectionString);

            if (dataType == RealDataType.auto_rain || dataType == RealDataType.manual_rain)
            {
                List<object> CheckKeys = new List<object>() { RealRainValueType.D22, RealRainValueType.D28, RealRainValueType.D82, RealRainValueType.D88 };
                CheckRainRealHealth(CheckKeys,CheckResult);
            }
            else if (dataType == RealDataType.auto_temp || dataType == RealDataType.manual_temp)
            {
                List<object> CheckKeys = new List<object>() { RealTempValueType.D12, RealTempValueType.D18, RealTempValueType.D2, RealTempValueType.D8 };
                CheckTempRealHealth(CheckKeys,CheckResult);
            }

            return CheckResult;

        }

        private DataTable CheckRainRealHealth(List<object> CheckKeys,DataTable checkResult)
        {
           
            //按日期分类
            Dictionary<DateTime, Dictionary<RealRainValueType, RainRealEntity>> Entities = new Dictionary<DateTime, Dictionary<RealRainValueType, RainRealEntity>>();
            DateTime cur = BeginDate;
            while (cur <= EndDate)
            {
                Entities.Add(cur, new Dictionary<RealRainValueType, RainRealEntity>());
                cur = cur.AddDays(1);
            }

            RainRealEntity[] entities = RepositoryRailReal.GetEntitiesWithDate(BeginDate, EndDate);
            if (CheckLackRecord)
            {
                foreach (RainRealEntity entity in entities)
                    Entities[entity.Date].Add(entity.Type, entity);

                foreach (KeyValuePair<DateTime, Dictionary<RealRainValueType, RainRealEntity>> pair in Entities)
                {
                    if (pair.Value.Count == CheckKeys.Count)
                        continue;
                    foreach (RealRainValueType key in CheckKeys)
                    {
                        if (!pair.Value.ContainsKey(key))
                            checkResult.Rows.Add(new object[] { "缺少记录", RepositoryRailReal.TableName, pair.Key.ToString("yyyy-MM-dd"), key.ToString() });
                    }
                }
            }

            foreach (RainRealEntity entity in entities)
            {
                if (entity.Value.Length <= 5)
                {
                    if (CheckEmptyValue)
                        checkResult.Rows.Add(new object[] { "空Value", RepositoryRailReal.TableName, entity.Date.ToString("yyyy-MM-dd"), entity.Type.ToString() });
                }
                else
                {
                    if (CheckValue)
                    {
                        ResetStations();
                        CheckData(entity.Value, entity.Date, entity.Type.ToString(), RepositoryRailReal.TableName, checkResult);
                    }
                    
                }
            }

            return checkResult;

        }

        private DataTable CheckTempRealHealth(List<object> CheckKeys,DataTable checkResult)
        {

            //按日期分类
            Dictionary<DateTime, Dictionary<RealTempValueType, TempRealEntity>> Entities = new Dictionary<DateTime, Dictionary<RealTempValueType, TempRealEntity>>();
            DateTime cur = BeginDate;
            while (cur <= EndDate)
            {
                Entities.Add(cur, new Dictionary<RealTempValueType, TempRealEntity>());
                cur = cur.AddDays(1);
            }

            TempRealEntity[] entities = RepositoryTempReal.GetEntitiesWithDate(BeginDate, EndDate);
            if (CheckLackRecord)
            {
                foreach (TempRealEntity entity in entities)
                    Entities[entity.Date].Add(entity.Type, entity);

                foreach (KeyValuePair<DateTime, Dictionary<RealTempValueType, TempRealEntity>> pair in Entities)
                {
                    if (pair.Value.Count == CheckKeys.Count)
                        continue;
                    foreach (RealTempValueType key in CheckKeys)
                    {
                        if (!pair.Value.ContainsKey(key))
                            checkResult.Rows.Add(new object[] { "缺少记录", RepositoryTempReal.TableName, pair.Key.ToString("yyyy-MM-dd"), key.ToString() });
                    }
                }
            }

            foreach (TempRealEntity entity in entities)
            {
                if (entity.Value.Length <= 5)
                {
                    if (CheckEmptyValue)
                        checkResult.Rows.Add(new object[] { "空Value", RepositoryTempReal.TableName, entity.Date.ToString("yyyy-MM-dd"), entity.Type.ToString() });
                }
                else
                {
                    if (CheckValue)
                    {
                        ResetStations();
                        CheckData(entity.Value, entity.Date, entity.Type.ToString(), RepositoryTempReal.TableName, checkResult);
                    }

                }
            }

            return checkResult;

        }

        public bool CheckData(string value, DateTime date, string type, string tableName, DataTable CheckResult)
        {
            bool result = true;

            string[] ss = value.Split('|');
            foreach (string s in ss)
            {
                if (s.Length < 5)
                    continue;
                string station = s.Substring(0, 5);
                bool r = FindStation(station);
                if (r == false && CheckAbnormalStation)
                    CheckResult.Rows.Add(new object[] { string.Format("Value中出现非常站点{0}", station), tableName, date.ToString("yyyy-MM-dd"), type });

            }
            List<string> more;
            List<string> miss;
            CheckStations(out more, out miss);
            if (more.Count > 0)
            {
                result = false;
                string r = string.Join(",", more);
                if (CheckRepeatStation)
                    CheckResult.Rows.Add(new object[] { string.Format("Value中多次出现站号为{0}的记录", r), tableName, date.ToString("yyyy-MM-dd"), type });
            }

            if (miss.Count > 0)
            {
                result = false;
                string r = string.Join(",", miss);
                if (CheckLackStation)
                    CheckResult.Rows.Add(new object[] { string.Format("Value 丢失站 {0}", r), tableName, date.ToString("yyyy-MM-dd"), type });
            }

            return result;
        }

        private void ResetStations()
        {
            RealStationCompareRepository repository = new RealStationCompareRepository(ConfigurationManager.AppSettings["ConnectionString"]);

            Dictionary<string, int> stations;
            if (DataType == RealDataType.auto_rain || DataType == RealDataType.auto_temp)
                stations = _autoStations;
            else
                stations = _manualStations;

            if (stations.Count == 0)
            {
                ForeRealStationCompareEntity[] entitys = repository.GetAllRecord(GetCompareType());
                foreach (ForeRealStationCompareEntity entity in entitys)
                    stations[entity.ForeStation] = 0;
            }
            else
            {

                Dictionary<string, int> newStations = new Dictionary<string, int>();
                foreach (string key in stations.Keys)
                    newStations[key] = 0;

                if (DataType == RealDataType.auto_rain || DataType == RealDataType.auto_temp)
                    _autoStations = newStations;
                else
                    _manualStations = newStations;

            }
        }

        private bool FindStation( string station)
        {
            bool result = true;

            Dictionary<string, int> stations;
            if (DataType == RealDataType.auto_rain || DataType == RealDataType.auto_temp)
                stations = _autoStations;
            else
                stations = _manualStations;
        
            if (stations.ContainsKey(station))
                stations[station] += 1;
            else
                result = false;
 
            return result;
        }

        private void CheckStations(out List<string> more, out List<string> miss)
        {
            more = new List<string>();
            miss = new List<string>();

            Dictionary<string, int> stations;
            if (DataType == RealDataType.auto_rain || DataType == RealDataType.auto_temp)
                stations = _autoStations;
            else
                stations = _manualStations;

            foreach (KeyValuePair<string, int> pair in stations)
            {
                if (pair.Value == 0)
                    miss.Add(pair.Key);

                if (pair.Value > 1)
                    more.Add(pair.Key);
            }

           
        }

        public RealStationCompareType GetCompareType()
        {

            if (DataType == RealDataType.auto_rain || DataType == RealDataType.auto_temp)
                return RealStationCompareType.Normal_Auto;
            else
                return RealStationCompareType.Normal_Manual;
        }


    }
}
